package com.infra.micro.quartz.domain.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.infra.common.resp.Page;
import com.infra.common.resp.Response;
import com.infra.common.util.BizUtils;
import com.infra.micro.quartz.domain.core.QuartzJobManage;
import com.infra.micro.quartz.domain.entity.QuartzJobPO;
import com.infra.micro.quartz.domain.repository.QuartzJobRepository;
import com.infra.micro.quartz.domain.service.QuartzJobService;
import com.infra.micro.quartz.model.req.QueryQuartzJobReq;
import com.infra.micro.quartz.model.vo.QuartzJobVO;
import org.quartz.CronExpression;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

@Service
public class QuartzJobServiceImpl implements QuartzJobService {

    private final QuartzJobRepository quartzJobRepository;

    private final QuartzJobManage quartzJobManage;

    public QuartzJobServiceImpl(QuartzJobRepository quartzJobRepository, QuartzJobManage quartzJobManage) {
        this.quartzJobRepository = quartzJobRepository;
        this.quartzJobManage = quartzJobManage;
    }


    /**
     * 根据暂停的状态查询列表
     *
     * @param isPause
     * @return
     */
    public List<QuartzJobPO> queryList(boolean isPause) {
        return quartzJobRepository.queryList(isPause);
    }

    /**
     * 暂停Job
     *
     * @param quartzJob
     * @return
     */
    @Override
    public boolean updateIsPause(QuartzJobVO quartzJob) {
        if (quartzJob.isPause()) {
            quartzJobManage.resumeJob(quartzJob);
            quartzJob.setPause(false);
        } else {
            quartzJobManage.pauseJob(quartzJob.getJobId());
            quartzJob.setPause(true);
        }

        return quartzJobRepository.updateIsPauseById(quartzJob.getJobId(), quartzJob.isPause());
    }

    public Response<Boolean> create(QuartzJobVO quartzJobVO) {
        if (!CronExpression.isValidExpression(quartzJobVO.getCronExpression())) {
            return Response.error("cron表达式格式错误！");
        }

        boolean result = quartzJobRepository.insert(quartzJobVO);
        if (result) {
            quartzJobManage.addJob(quartzJobVO);
            return Response.success(true, "创建Job成功！");
        }

        return Response.error("创建Job失败, 请重试！");
    }

    public Response<Boolean> update(Long jobId, QuartzJobVO quartzJobVO) {
        quartzJobVO.setJobId(jobId);
        if (!CronExpression.isValidExpression(quartzJobVO.getCronExpression())) {
            return Response.error("cron表达式格式错误！");
        }

        boolean result = quartzJobRepository.update(quartzJobVO);
        if (result) {
            quartzJobManage.updateJobCron(quartzJobVO);
            return Response.success(true, "更新Job成功！");
        }

        return Response.error("更新Job失败, 请重试！");
    }

    @Override
    public void execution(QuartzJobVO quartzJob) {
        quartzJobManage.runJobNow(quartzJob);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchDeleteByIds(Set<Long> jobIds) {
        jobIds.forEach(this::deleteById);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteById(Long jobId) {
        QuartzJobPO sysQuartzJobPO = quartzJobRepository.queryById(jobId);
        if (sysQuartzJobPO == null) {
            return false;
        }

        quartzJobManage.deleteJob(jobId);
        quartzJobRepository.deleteById(jobId);
        return true;
    }

    public Response<QuartzJobVO> queryById(Long jobId) {
        QuartzJobPO quartzJobPO = quartzJobRepository.queryById(jobId);
        return quartzJobPO == null ? Response.error("jobId无效！") : Response.success(buildQuartzJobVO(quartzJobPO), "查询成功！");
    }

    public Response<Page<QuartzJobVO>> queryListByPage(QueryQuartzJobReq req) {
        PageInfo<QuartzJobPO> pageInfo = PageHelper.startPage(req.getPageIndex(), req.getPageSize(), BizUtils.buildOrderByClause(req.getSortField(), req.getSortType()))
                .doSelectPageInfo(() -> quartzJobRepository.queryListByPage(req));

        final Page page = Page.builder(pageInfo.getTotal(), req);
        page.getPageList().addAll(buildQuartzJobVOList(pageInfo.getList()));

        return Response.success(page);
    }

    private List<QuartzJobVO> buildQuartzJobVOList(List<QuartzJobPO> list) {
        if (CollectionUtils.isEmpty(list)) {
            return new ArrayList<>();
        }

        List<QuartzJobVO> result = new ArrayList<>(list.size());
        list.forEach(item -> result.add(buildQuartzJobVO(item)));
        return result;
    }

    private QuartzJobVO buildQuartzJobVO(QuartzJobPO record) {
        QuartzJobVO result = new QuartzJobVO();
        BeanUtils.copyProperties(record, result);
        return result;
    }
}
